//
// Created by LiuYou on 2021/10/27.
//

#include <iostream>
#include <cstring>


static const int BUF_SIZE = 1024;
static FILE* fp;


/*
 * 参看给定的文件每一行有多少个字符。
 */
int main(int argc, char** argv) {
    if (argc < 2) {
        fprintf( stderr, "用法: %s filename\n", argv[0] );
        return 1;
    }

    fp = fopen( argv[1], "r" );
    if (fp == nullptr) {
        perror( "fopen()" );
        return 1;
    }
    atexit( []() -> void {
        fclose( fp );
    } );


    // 一次读一整行。
//    getline()


    // todo 笔记: 必须初始化 lineBuffer 和 lineLength 。
    //  非常必须！！！！
    char* lineBuffer{};
    size_t lineLength{};

//    char buf[BUF_SIZE]{};
//    lineBuffer = buf;
//    lineLength = BUF_SIZE;

    int lineNum{};
    while (true) {
        /*
         * todo 笔记:
         *  这里我想明白为什么使用一个二级指针了,
         *  因为函数内部是要回填一级指针的值的,
         *  这个一级指针的值是扩容后变化的, 所以需要把这个扩容后的
         *  指针值赋值给实参的这个一级指针, 所以将这个参数设计为了
         *  指向这个一级指针内存的二级指针, 方便回填这个一级指针的地址。
         *  跟第二个参数 size_t* n 是一个道理, n 也是需要回填的。
         */
        ssize_t readBytes = getline( &lineBuffer, &lineLength, fp );
        if (readBytes < 0) {
            break;
        }
        ++lineNum;

        // 下面这两句是等效的。
        printf( "%d 行的字节数为: %zd。 ", lineNum, readBytes );
        printf( "%d 行的字节数为: %zd。\n", lineNum, strlen( lineBuffer ));

        printf( "%zu\n", lineLength );
    }


    // todo 注意: 笔记: 不推荐这样使用。因为我们不知道 getline(); 内部
    //  动态内存分配使用的是哪个函数。因为动态内存分配不仅仅只有 malloc();函数,
    //  还有其他函数。
    //  这个内存泄漏是可控的内存泄漏。
    //  所以不要使用 free(lineBuffer);
//    free( lineBuffer );


    return 0;
}
// 运行结果:
/*
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2/src/io$ ./a.out IO-getline1.cpp
1 行的字节数为: 4。 1 行的字节数为: 4。
120
2 行的字节数为: 37。 2 行的字节数为: 37。
120
3 行的字节数为: 4。 3 行的字节数为: 4。
120
4 行的字节数为: 2。 4 行的字节数为: 2。
120
5 行的字节数为: 21。 5 行的字节数为: 21。
120
6 行的字节数为: 20。 6 行的字节数为: 20。
120
7 行的字节数为: 2。 7 行的字节数为: 2。
120
8 行的字节数为: 2。 8 行的字节数为: 2。
120
9 行的字节数为: 35。 9 行的字节数为: 35。
120
10 行的字节数为: 18。 10 行的字节数为: 18。
120
11 行的字节数为: 2。 11 行的字节数为: 2。
120
12 行的字节数为: 2。 12 行的字节数为: 2。
120
13 行的字节数为: 4。 13 行的字节数为: 4。
120
14 行的字节数为: 56。 14 行的字节数为: 56。
120
15 行的字节数为: 5。 15 行的字节数为: 5。
120
16 行的字节数为: 35。 16 行的字节数为: 35。
120
17 行的字节数为: 21。 17 行的字节数为: 21。
120
18 行的字节数为: 62。 18 行的字节数为: 62。
120
19 行的字节数为: 19。 19 行的字节数为: 19。
120
20 行的字节数为: 7。 20 行的字节数为: 7。
120
21 行的字节数为: 2。 21 行的字节数为: 2。
120
22 行的字节数为: 33。 22 行的字节数为: 33。
120
23 行的字节数为: 26。 23 行的字节数为: 26。
120
24 行的字节数为: 30。 24 行的字节数为: 30。
120
25 行的字节数为: 19。 25 行的字节数为: 19。
120
26 行的字节数为: 7。 26 行的字节数为: 7。
120
27 行的字节数为: 28。 27 行的字节数为: 28。
120
28 行的字节数为: 23。 28 行的字节数为: 23。
120
29 行的字节数为: 10。 29 行的字节数为: 10。
120
30 行的字节数为: 2。 30 行的字节数为: 2。
120
31 行的字节数为: 2。 31 行的字节数为: 2。
120
32 行的字节数为: 30。 32 行的字节数为: 30。
120
33 行的字节数为: 17。 33 行的字节数为: 17。
120
34 行的字节数为: 2。 34 行的字节数为: 2。
120
35 行的字节数为: 2。 35 行的字节数为: 2。
120
36 行的字节数为: 25。 36 行的字节数为: 25。
120
37 行的字节数为: 26。 37 行的字节数为: 26。
120
38 行的字节数为: 2。 38 行的字节数为: 2。
120
39 行的字节数为: 29。 39 行的字节数为: 29。
120
40 行的字节数为: 25。 40 行的字节数为: 25。
120
41 行的字节数为: 30。 41 行的字节数为: 30。
120
42 行的字节数为: 2。 42 行的字节数为: 2。
120
43 行的字节数为: 20。 43 行的字节数为: 20。
120
44 行的字节数为: 20。 44 行的字节数为: 20。
120
45 行的字节数为: 12。 45 行的字节数为: 12。
120
46 行的字节数为: 25。 46 行的字节数为: 25。
120
47 行的字节数为: 69。 47 行的字节数为: 69。
120
48 行的字节数为: 66。 48 行的字节数为: 66。
120
49 行的字节数为: 94。 49 行的字节数为: 94。
120
50 行的字节数为: 94。 50 行的字节数为: 94。
120
51 行的字节数为: 103。 51 行的字节数为: 103。
120
52 行的字节数为: 86。 52 行的字节数为: 86。
120
53 行的字节数为: 13。 53 行的字节数为: 13。
120
54 行的字节数为: 70。 54 行的字节数为: 70。
120
55 行的字节数为: 30。 55 行的字节数为: 30。
120
56 行的字节数为: 20。 56 行的字节数为: 20。
120
57 行的字节数为: 11。 57 行的字节数为: 11。
120
58 行的字节数为: 20。 58 行的字节数为: 20。
120
59 行的字节数为: 2。 59 行的字节数为: 2。
120
60 行的字节数为: 43。 60 行的字节数为: 43。
120
61 行的字节数为: 73。 61 行的字节数为: 73。
120
62 行的字节数为: 84。 62 行的字节数为: 84。
120
63 行的字节数为: 2。 63 行的字节数为: 2。
120
64 行的字节数为: 40。 64 行的字节数为: 40。
120
65 行的字节数为: 7。 65 行的字节数为: 7。
120
66 行的字节数为: 2。 66 行的字节数为: 2。
120
67 行的字节数为: 2。 67 行的字节数为: 2。
120
68 行的字节数为: 15。 68 行的字节数为: 15。
120
69 行的字节数为: 3。 69 行的字节数为: 3。
120
liuyou@liuyou-virtual-machine:~/CLionProjects/LinuxEnvironmentProgramming2/src/io$


 todo 笔记: 即可得出结论, 是先通过 malloc(); 分配了 120 个字节长度的缓冲区, 可能是这样的:

 *lineptr = malloc(120 * sizeof(char));
 *n = 120;

 当缓冲区的大小将要超过 120 个字节时, 就会 realloc();。
 120 -> 240 -> 480 -> 960 -> ...


 */